package com.itheima.reggie.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.reggie.Dto.OrdersDto;
import com.itheima.reggie.common.BaseContext;
import com.itheima.reggie.common.CustomException;
import com.itheima.reggie.entity.*;
import com.itheima.reggie.mapper.OrdersMapper;
import com.itheima.reggie.service.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @author zhoufei
 */
@Service
public class OrdersServiceImpl extends ServiceImpl<OrdersMapper, Orders> implements OrdersService {

    @Autowired
    private ShoppingCartService shoppingCartService;

    @Autowired
    private UserService userService;

    @Autowired
    private AddressBookService addressBookService;

    @Autowired
    private OrderDetailService orderDetailService;


    /**
     * 重写自定义下单方法
     * @param orders
     */
    @Override
    public void submit(Orders orders) {
        //1.获取当前登录用户的Id,查询该用户购物车的数据
        Long userId = BaseContext.getCurrentId();
        //2.查询当前用户的购物车数据
        LambdaQueryWrapper<ShoppingCart> queryWrapper = new LambdaQueryWrapper<ShoppingCart>();
        queryWrapper.eq(ShoppingCart::getUserId,userId);
        List<ShoppingCart> shoppingCarts = shoppingCartService.list(queryWrapper);
        //3.判断该用户购物车是否存在数据
        if (shoppingCarts == null || shoppingCarts.size() == 0){
            //购物车无数据，不能下单，抛出异常
            throw new CustomException("购物车为空，无法下单");
        }
        //存在，将订单表需要的信息存储到数据库中
        //4.获取用户的数据，注入依赖，根据用户Id查询当前用户的用户表信息
        User user = userService.getById(userId);
        //5.获取地址簿信息，注入依赖，查询地址信息添加到订单表中
            //5.1订单表中存在地址簿的外键Id,获取该外键Id(在地址表中是主键),查询地址簿表
            Long addressBookId = orders.getAddressBookId();
            AddressBook addressBook = addressBookService.getById(addressBookId);
            //5.2判断地址信息是否存在
                if (addressBook == null){
                    //5.2.1不存在，无法下单，抛出异常
                    throw new CustomException("无地址信息，无法下单");
                }
        //用户下单成功未操作两张表：订单表和订单明细表
        //定义变量：
            long orderId = IdWorker.getId();
            AtomicInteger orderPrice= new AtomicInteger();
        //6.将数据存储到订单明细中（查看订单明细表需要存储的信息）
            //6.1存储菜品名，口味，菜品总金额，通过用户购物车可以获取这些数据
        List<OrderDetail> orderDetails = shoppingCarts.stream().map((item) -> {
            //6.2创建订单明细表对象存储信息
            OrderDetail orderDetail = new OrderDetail();
            //6.3拷贝数据
            BeanUtils.copyProperties(item, orderDetail);
            //6.4还需添加订单Id和订单总金额
            //6.4.1订单Id因为订单还未保存到数据库，所以需要先产生，后将产生的Id保存到数据库（IdWorker方法生成）
            orderDetail.setOrderId(orderId);
            //6.4.2添加订单总金额
            orderPrice.addAndGet(((item.getAmount().intValue() * item.getNumber())));
            return orderDetail;
        }).collect(Collectors.toList());
        //6.5注入依赖，调用方法添加数据
            orderDetailService.saveBatch(orderDetails);

        //7.将数据存储到订单表（查看订单表需要存储的信息）
            //7.1将信息封装到订单对象中
            orders.setId(orderId);
            orders.setOrderTime(LocalDateTime.now());
            orders.setCheckoutTime(LocalDateTime.now());
            orders.setStatus(2);
            orders.setAmount(new BigDecimal(orderPrice.intValue()));
            orders.setUserId(userId);
            orders.setNumber(String.valueOf(orderId));
            orders.setUserName(user.getName());
            orders.setConsignee(addressBook.getConsignee());
            orders.setPhone(addressBook.getPhone());
            orders.setAddress(addressBook.getDetail());
            //7.2调用方法，存入到表中
            this.save(orders);
        //8.下单完成后，清空购物车
        shoppingCartService.remove(queryWrapper);
    }

    /**
     * 重写用户端查询订单方法
     * @param page
     * @param pageSize
     * @return
     */
    @Override
    public Page<OrdersDto> getUserOrders(int page, int pageSize) {
        //1.构造分页对象
        Page<Orders> pageInfo = new Page<>(page,pageSize);
        //2.构造查询对象
        LambdaQueryWrapper<Orders> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByDesc(Orders::getOrderTime);
        //3.执行查询
        this.page(pageInfo,queryWrapper);

        //注：此时查询出的结果中每个订单的信息，不存在商品总数，需要通过扩展类进行封装
        //4.构造扩展类分页对象
        Page<OrdersDto> dtoPage = new Page<>();
        //5.拷贝数据到扩展类，并忽略掉Orders分页对象中的records数据（因为该数据不完整，差商品总数）
        BeanUtils.copyProperties(pageInfo,dtoPage,"records");
        //6.获取Orders分页对象中的订单数据
        List<Orders> records = pageInfo.getRecords();
        //7.对每一订单数据遍历，并封装到dtoPage中
        List<OrdersDto> ordersDtos = records.stream().map((record) -> {
            //7.1创建扩展类对象接收数据
            OrdersDto ordersDto = new OrdersDto();
            //7.2拷贝数据
            BeanUtils.copyProperties(record, ordersDto);
            //7.3添加订单商品总数（获取订单表中得到订单id,通过订单id去订单明细表中查询订单明细Id(查询的是一个集合)，遍历该集合，通过每一个id查询对象商品的数量）
            Long orderId = ordersDto.getId();
            LambdaQueryWrapper<OrderDetail> queryWrapper1 = new LambdaQueryWrapper<>();
            queryWrapper1.eq(OrderDetail::getOrderId, orderId);
            List<OrderDetail> orderDetails = orderDetailService.list(queryWrapper1);
            Integer sumNum = 0;
            for (OrderDetail orderDetail : orderDetails) {
                sumNum += orderDetail.getNumber();
            }
            ordersDto.setSumNum(sumNum);
            return ordersDto;
        }).collect(Collectors.toList());
        //8.将完整的数据添加到扩展类分页对象中
        dtoPage.setRecords(ordersDtos);

        return dtoPage;
    }
}
